package dk.sdu.mmmi.opn.rmi.observer;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashSet;
import java.util.Set;

/**
 * Distributed observer pattern implementation: implementation of the observable
 * Implementation of a remote observable object implementing the interaction between
 * the IRemoteObservable and IRemoteObserver interfaces.
 * Note: no explicit error handling, only minimal scalability concerns etc 
 * @author ups
 */
@SuppressWarnings("serial")
public class RemoteObservable extends UnicastRemoteObject implements IRemoteObservable {

	/**
	 * The remote observers
	 */
	private Set<IRemoteObserver> observers = new HashSet<IRemoteObserver>();
	
	/**
	 * Create observable object as a remote object
	 */
	public RemoteObservable() throws RemoteException {
		super();
	}

	/**
	 * Start observing this subject, according to the observer pattern
	 */
	public void addObserver(IRemoteObserver observer) {
		observers.add(observer);
	}

	/**
	 * Stop observing this subject, according to the observer pattern
	 */
	public void deleteObserver(IRemoteObserver observer) {
		observers.remove(observer);
	}

	/**
	 * Publish an update to all observers, possibly in parallel
	 * @param event the object describing the update
	 */
	public void notifyObservers(Object event) {
		observers.parallelStream().forEach(observer -> { // Enable parallel notification
			try { 
				observer.update(this,event); 
			} 
			catch(RemoteException e) { 
				System.err.println("Exception on update of client "+observer+": "+e);
			}
		});
	}
}
